package cn.biplam.back.bean.tree;

import java.io.Serializable;

import cn.biplam.back.bean.mdmanage.IndexTableImp;
import cn.biplam.common.bean.tree.IndexTableSimple;
import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.Operator;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.opcode.SysManageCode.TreeIndexCode;
import cn.biplam.common.paramters.MdParam.Index_Node_Move_Type;
import cn.biplam.common.paramters.TreeParam.Index_Tree_Node_Type;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.tree.TreeIndexFields;

/**
 *  树索引表数据操作对象
 * @author XiaoRuxing Nov 13, 20092:29:35 PM
 * @version 1.0
 */
public class IndexTableSimpleImp  extends IndexTableSimple implements Serializable{

	private static final long serialVersionUID = 2238245253653790916L;
	private String userId;
	private String indexTabName;
	private TreeIndexFields treeFields;
	
	/**
	 * 	创建树索引表数据操作对象
	 * @param userId       用户ID
	 * @param indexTabName 索引表名
	 */
	public IndexTableSimpleImp(String userId, String indexTabName) throws ErrorMessage{
		this.userId = userId;
		this.indexTabName = indexTabName;
		treeFields=TreeIndexFields.getTreeFields(indexTabName);
	}

	/**
	 *  删除索引记录
	 * @param nodeId 索引ID
	 * @param getSql 是否获取SQL
	 * @return getSql值为true: 不进行数据库提交返回删除节点的SQL语句<U>(OperatorResult.getSqls方法获取)</U><BR>
	 *         getSql值为false: 删除节点执行是否成功)<U>(OperatorResult.getDmlResult方法获取)</U><BR>
	 */
	@Override
	public OperatorResult delete(String nodeId, boolean getSql)
			throws ErrorMessage {
		OperatorResult or = null;
		DataFilter filter = new DataFilter();
		setTableName(filter);
		IndexTableImp iti = new IndexTableImp(userId,indexTabName,nodeId);
		if(!iti.isExist()){//如果节点不存在返回
			or=new OperatorResult();
			or.setDmlResult(false);
			or.setOperatorInfo("Node is not exists");
		}else{
			filter.put(treeFields.getNodeId(), nodeId);
			if(iti.getOperatorType().equals(Index_Tree_Node_Type.ROOT_THEME.toString())){//如果是根节点执行根节点删除
				or = Operator.get(TreeIndexCode.Delete_Root_By_Index_Id, userId, filter,getSql);
			}else{
				or = Operator.get(TreeIndexCode.Delete_By_Index_Id, userId, filter,getSql);
			}
		}
		return or;
	}

	/**
	 *  删除虚根节点记录
	 * @param nodeId 虚根节点ID
	 * @return 删除是否成功
	 */
	@Override
	public OperatorResult deleteVirtualNode(String nodeId,boolean isGetSql) throws ErrorMessage {
		DataFilter filter = new DataFilter();
		setTableName(filter);
		filter.put(treeFields.getNodeId(), nodeId);
		return Operator.get(TreeIndexCode.Delete_Virtual_Root, userId, filter,isGetSql);
	}

	/**
	 *   插入节点(不适用于虚拟根节点)<BR>
	 *    <UL>适用场合:
	 *  	<li> 普通节点或根节点插入<BR>
	 *  	<li> 批量插入时插入当前层级节点的第一个节点的SQL
	 *  </UL>
	 * @param operatorType 节点类型<I>(不能为空,数据类型为Index_Tree_Node_Type)</I>
	 * @param parentId     父节点索引ID<I>(普通节点插入必须传入父节点索引ID,根节点插入建议传入父节点索引ID)</I>
	 * @param nodeId       节点ID<I>(可以为空)</I>
	 * @param nodeName     名称<I>(可以为空)</I>
	 * @param nodeCode     节点真实ID<I>(可以为空)</I>
	 * @param nodeDesc     描述<I>(可以为空)</I>
	 * @param nodeType     节点索引<I>(可以为空)</I>
	 * @param getSql       是否获取插入SQL
	 * @return  节点ID<U>(OperatorResult.getLastRowId方法获取)</U><BR>
	 *          节点排序号<U>(OperatorResult.getValue方法获取)</U><BR>
	 *          getSql值为true:不进行数据库提交返回插入节点的SQL语句<U>(OperatorResult.getSqls方法获取)</U><BR>
	 *          getSql值为false:将节点插入到数据库执行是否成功)<U>(OperatorResult.getDmlResult方法获取)</U><BR>
	 * @throws ErrorMessage 
	 */
	@Override
	public OperatorResult insertFirst(String operatorType, String parentId,
			String nodeId, String nodeName, String nodeCode, String nodeDesc,
			String nodeType, boolean getSql) throws ErrorMessage {
		DataFilter filter = this.getInsertParam(nodeId, parentId, nodeName, nodeCode, operatorType, nodeDesc, nodeType,
				null, null);
		return Operator.get(TreeIndexCode.Insert_First, userId, filter, getSql);
	}

	/**
	 *  获取非第一次插入节点的SQL(不适用于虚拟根节点)<BR>
	 *  适用场合:获取批量插入节点时插入当前级别第一个节点后面节点的SQL
	 * @param operatorType 节点类型<I>(不能为空,数据类型为Index_Tree_Node_Type)</I>
	 * @param parentId     父节点索引ID<I>(普通节点插入必须传入父节点索引ID,根节点插入建议传入父节点索引ID)</I>
	 * @param preSequence  当前节点的哥哥的排序号(不能为空,值由上一次插入的结果中获取)
	 * @param preOperatorType 当前节点的哥哥的节点类型(如果为空则认为当前节点的哥哥节点类型与当前节点相同)
	 * @param nodeId       节点ID<I>(可以为空)</I>
	 * @param nodeName     名称<I>(可以为空)</I>
	 * @param nodeCode     节点真实ID<I>(可以为空)</I>
	 * @param nodeDesc     描述<I>(可以为空)</I>
	 * @param nodeType     节点索引<I>(可以为空)</I>
	 * @return  节点ID<U>(OperatorResult.getLastRowId方法获取)</U><BR>
	 *          节点排序号<U>(OperatorResult.getValue方法获取)</U><BR>
	 *          返回插入节点的SQL语句<U>(OperatorResult.getSqls方法获取)</U><BR>
	 * @throws ErrorMessage 
	 */
	@Override
	public OperatorResult insertSecond(String operatorType, String parentId,
			String preSequence, String preOperatorType, String nodeId,
			String nodeName, String nodeCode, String nodeDesc, String nodeType) throws ErrorMessage {
		DataFilter filter = this.getInsertParam(nodeId, parentId, nodeName, nodeCode, operatorType, nodeDesc, nodeType, 
				preSequence, preOperatorType);
		return Operator.get(TreeIndexCode.Insert_Second, userId, filter,true);
	}

	/**
	 * 插入虚拟根节点
	 * @param nodeId      节点ID<I>(可以为空)</I>
	 * @param nodeCode    节点代码<I>(可以为空)</I>
	 * @param nodeName    节点名称<I>(可以为空)</I>
	 * @param nodeDesc    节点描述<I>(可以为空)</I>
	 * @param getSql      是否获取插入SQL
	 * @return 节点ID<U>(OperatorResult.getLastRowId方法获取)</U><BR>
	 * 		   getSql值为true:不进行数据库提交返回插入节点的SQL语句<U>(OperatorResult.getSqls方法获取)</U><BR>
	 *         getSql值为false:将节点插入到数据库执行是否成功)<U>(OperatorResult.getDmlResult方法获取)</U><BR>
	 * @throws ErrorMessage 
	 */
	@Override
	public OperatorResult insertVirtualRoot(String nodeId, String nodeCode,
			String nodeName, String nodeDesc, boolean getSql) throws ErrorMessage {
		DataFilter filter = this.getInsertParam(nodeId, null, nodeName, nodeCode, 
				null, nodeDesc,
				null, null, null);
		return Operator.get(TreeIndexCode.Insert_Virtual_Root, userId, filter,getSql);
	}

	/**
	 *  索引表移动<BR>
	 * <ul>移动方式有：
	 * 	<li>移动到节点前     只支持同类型节点间移动
	 * 	<li>移动到节点后     只支持同类型节点间移动
	 * 	<li>移动到节点儿子尾  移动到的是同类型兄弟的末尾(比如当移动一个主题到目标主题的儿子尾时,移动到的是目标主题所有子主题的末尾而不是所有儿子的末尾)
	 *  <li>移动到节点儿子头  移动到的是同类型兄弟的头<BR>
	 *  <font COLOR='red'>注意:不支持虚拟根节点和根节点的移动,移动到节点的儿子时不支持向下移动即主题不能移动到叶子节点的儿子</font><BR>
	 * </ul> 
	 * @param srcId    被移动节点ID
	 * @param trgId    移动目标节点ID
	 * @param moveType 移动类型(Index_Node_Move_Type)
	 * @return 移动是否成功
	 */
	@Override
	public OperatorResult move(String srcId, String trgId,
			Index_Node_Move_Type moveType) throws ErrorMessage {
		DataFilter treeFilter = new DataFilter();
		setTableName(treeFilter);
		treeFilter.put("moved_node_id", srcId);
		treeFilter.put("move_to_node_id", trgId);
		treeFilter.put("move_type", moveType);
		return Operator.get(TreeIndexCode.Move_By_Index_Id, userId, treeFilter);
	}

	/**
	 *  更新索引表
	 *  @param nodeId    索引Id
	 *  @param nodeName  索引名称
	 *  @param nodeDesc  索引描述
	 *  @param nodeCode  索引真实ID
	 *  @param getSql    是否获取SQL 
	 *  @return getSql值为true: 不进行数据库提交返回更新节点的SQL语句<U>(OperatorResult.getSqls方法获取)</U><BR>
	 *          getSql值为false: 更新节点执行是否成功)<U>(OperatorResult.getDmlResult方法获取)</U><BR>
	 */
	@Override
	public OperatorResult update(String nodeId, String nodeName,
			String nodeDesc, String nodeCode, boolean getSql)
			throws ErrorMessage {
		DataFilter filter = new DataFilter();
		setTableName(filter);
		filter.put(treeFields.getNodeId(),nodeId);
		filter.put(treeFields.getNodeName(),nodeName);
		filter.put(treeFields.getRealId(),nodeCode);
		filter.put(treeFields.getNodeDesc(), nodeDesc);
		return Operator.get(TreeIndexCode.Update_Index_Node, userId, filter, getSql);
	}
	
	/**
	 *  设置表名称
	 */
	private void setTableName(DataFilter filter) throws ErrorMessage{
		filter.put("table_name", indexTabName);
	}
	
	/**
	 *  设置添加记录参数
	 */
	private DataFilter getInsertParam(String nodeId,String parentId, String nodeName,
			String nodeCode, String operatorType,String nodeDesc,
			String nodeType,
			String nodeSequence,
			String preNodeType
			) throws ErrorMessage{
		DataFilter filter = new DataFilter();
		setTableName(filter);
		filter.put(treeFields.getNodeId(),nodeId);
		filter.put(treeFields.getNodeParent(),parentId);
		filter.put(treeFields.getNodeName(),nodeName);
		filter.put(treeFields.getRealId(),nodeCode);
		filter.put(treeFields.getOperatorType(),operatorType);
		filter.put(treeFields.getNodeDesc(), nodeDesc);
		filter.put(treeFields.getNodeType(), nodeType);
		//获取获取二次插入SQL
		filter.put(treeFields.getNodeSequence(), nodeSequence);
		filter.put("pre"+treeFields.getOperatorType(), preNodeType);
		return filter;
	}
}
